﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace Xwltz.Framework.Test
{
    public class SocketMessage : IDisposable
    {
        public byte[] MessageBuffer;
        public int MessageId;

        public SocketMessage(int messageId, byte[] messageBuffer)
        {
            MessageId = messageId;
            MessageBuffer = messageBuffer;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool flag)
        {
            if (flag) MessageBuffer = null;
        }
    }

    public class ParserMessage
    {
        //包头1
        private const short T1 = 0x55;

        //包头2
        private const short T2 = 0xAA;

        //字节数常量 两个包头4个字节，一个消息id4个字节，封装消息长度 int32 4个字节
        private const int ConstLenght = 10;

        //默认是utf8的编码格式
        private readonly UTF8Encoding _utf8 = new UTF8Encoding();

        //用于存储剩余未解析的字节数
        private List<byte> _lBuff = new List<byte>(22);

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool flag)
        {
            if (!flag) return;
            var disposable2 = _utf8 as IDisposable;
            disposable2?.Dispose();
            var disposable = _lBuff as IDisposable;
            disposable?.Dispose();
        }

        public byte[] Encode(SocketMessage msg)
        {
            var ms = new MemoryStream();
            var bw = new BinaryWriter(ms, new UTF8Encoding());
            var msgBuffer = msg.MessageBuffer;

            #region 封装包头

            bw.Write(T1);
            bw.Write(T2);

            #endregion

            #region 包协议

            if (msgBuffer != null)
            {
                bw.Write(msgBuffer.Length + 4);
                bw.Write(msg.MessageId);
                bw.Write(msgBuffer);
            }
            else
            {
                bw.Write(0);
            }

            #endregion

            bw.Close();
            ms.Close();
            bw.Dispose();
            ms.Dispose();
            return ms.ToArray();
        }

        public List<SocketMessage> GetDcAppMess(byte[] buff, int len)
        {
            //拷贝本次的有效字节
            var b = new byte[len];
            Array.Copy(buff, 0, b, 0, b.Length);
            buff = b;
            if (_lBuff.Count > 0)
            {
                //拷贝之前遗留的字节
                _lBuff.AddRange(b);
                buff = _lBuff.ToArray();
                _lBuff.Clear();
                _lBuff = new List<byte>(2);
            }

            var list = new List<SocketMessage>();
            var ms = new MemoryStream(buff);
            var buffers = new BinaryReader(ms, _utf8);
            try
            {
                Label_00983:

                #region 包头读取

                //循环读取包头           
                //判断本次解析的字节是否满足常量字节数 
                if (buffers.BaseStream.Length - buffers.BaseStream.Position < ConstLenght)
                {
                    buff = buffers.ReadBytes((int) (buffers.BaseStream.Length - buffers.BaseStream.Position));
                    _lBuff.AddRange(buff);
                    return list;
                }

                var tt1 = buffers.ReadInt16();
                var tt2 = buffers.ReadInt16();
                if (!(tt1 == T1 && tt2 == T2))
                {
                    buffers.BaseStream.Seek(-3, SeekOrigin.Current);
                    goto Label_00983;
                }

                #endregion

                #region 包协议

                var offset = buffers.ReadInt32();

                #endregion

                #region 包解析

                //剩余字节数大于本次需要读取的字节数
                if (offset <= buffers.BaseStream.Length - buffers.BaseStream.Position)
                {
                    var msgId = buffers.ReadInt32();
                    buff = buffers.ReadBytes(offset - 4);
                    list.Add(new SocketMessage(msgId, buff));
                    if (buffers.BaseStream.Length - buffers.BaseStream.Position > 0) goto Label_00983;
                }
                else
                {
                    //剩余字节数刚好小于本次读取的字节数 存起来，等待接受剩余字节数一起解析
                    buff = buffers.ReadBytes((int) (buffers.BaseStream.Length - buffers.BaseStream.Position + ConstLenght));
                    _lBuff.AddRange(buff);
                }

                #endregion
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            finally
            {
                buffers.Dispose();
                buffers.Close();
                buffers.Dispose();
                ms.Close();
                ms.Dispose();
            }

            return list;
        }
    }
}